﻿using System;
using System.Xml.Linq;
using PengSW.NotifyPropertyChanged;
using static PengSW.RuntimeLog.RL;
using static PengSW.XmlHelper.XmlLinqHelper;

namespace PengSW.Schedule
{
    public abstract class ScheduleBase : NotifyPropertyChangedObject, ISchedule
    {
        #region 构造与撤销

        public virtual void Dispose()
        {
            if (IsStart) Stop();
        }

        #endregion

        #region 调度执行及相关参数

        public string Description { get { return !string.IsNullOrWhiteSpace(_Description) ? _Description : ToString(); } set { SetValue(ref _Description, value, nameof(Description)); } }
        private string _Description;

        public TimeSpan StartInterval { get => _StartInterval; set { SetValue(ref _StartInterval, value, nameof(StartInterval)); } }
        private TimeSpan _StartInterval = TimeSpan.Zero;

        public TimeSpan Interval { get { return _Interval; } set { SetValue(ref _Interval, value, nameof(Interval)); } }
        private TimeSpan _Interval = TimeSpan.FromSeconds(10);

        public DateTime NextDispatchTime { get { return _NextDispatchTime; } set { SetValue(ref _NextDispatchTime, value, nameof(NextDispatchTime)); } }
        private DateTime _NextDispatchTime = DateTime.MinValue;

        public bool IsStart { get { return _IsStart; } set { SetValue(ref _IsStart, value, nameof(IsStart)); } }
        private bool _IsStart = false;

        public bool IsDispatching { get { return _IsDispatching; } set { SetValue(ref _IsDispatching, value, nameof(IsDispatching)); } }
        private bool _IsDispatching = false;

        public virtual void Start()
        {
            if (IsStart) return;
            NextDispatchTime = DateTime.Now + StartInterval;
            IsStart = true;
        }

        public virtual void Stop()
        {
            if (!IsStart) return;
            IsStart = false;
        }

        protected abstract void _OnDispatch(object aContent);

        public virtual void OnDispatch(object aContent)
        {
            if (IsDispatching) return;
            IsDispatching = true;
            try
            {
                L($"{Description} dispatching....");
                _OnDispatch(aContent);
                L($"{Description} dispatch over.");
            }
            catch (Exception ex)
            {
                E(ex, $"[{Description}].OnDispatch");
            }
            IsDispatching = false;
        }

        #endregion

        #region 编辑

        public virtual bool IsEditable => !IsStart;

        public abstract void Edit();

        #endregion

        #region 序列化

        public virtual void ReadFromXml(XElement aXElement)
        {
            if (aXElement == null) return;
            Description = aXElement.GetAttributeValue(nameof(Description), _Description);
            StartInterval = aXElement.GetAttributeValue(nameof(StartInterval), TimeSpan.Zero);
            Interval = aXElement.GetAttributeValue(nameof(Interval), TimeSpan.FromSeconds(10));
        }

        public virtual XElement CreateXElement(string aXmlNodeName)
        {
            return new XElement(aXmlNodeName,
                CreateXAttribute("Type", GetType().Name),
                CreateXAttribute(nameof(Description), Description),
                CreateXAttribute(nameof(StartInterval), StartInterval),
                CreateXAttribute(nameof(Interval), Interval)
            );
        }

        #endregion
    }
}
